﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SharpSoft.DAOS
{
    using SharpSoft.Data;
    using SharpSoft.Data.DAOS;
    using SharpSoft.Models;

    public class TaskDAO : DAO
    {
        public TaskDAO(Database p_db, int p_userid = -1) : base(p_db, p_userid)
        {
        }
        protected override string InitScriptFileName => "task.txt";



        /// <summary>
        /// 获取需要立即执行的任务
        /// </summary>
        /// <param name="count">此次获取的最大数量</param>
        /// <param name="typeFlag">使用任务类型标识过滤</param>
        /// <returns></returns>
        public TaskModel[] GetFreeTasks(int count, string? typeFlag = null)
        {
            string filterFlag = "";
            if (typeFlag != null)
            {
                filterFlag = " AND `TypeFlag`=@typeFlag";
            }
            var sql = $"SELECT * FROM `Task` WHERE `State`=0{filterFlag} AND `IsExpired`=0 AND (`PresetTime` IS NULL OR `PresetTime`<=NOW()) ORDER BY `Priority` DESC,`PresetTime` ASC LIMIT {count} FOR UPDATE;";
            return db.ExecuteArray<TaskModel>(sql, new { typeFlag });
        }
        /// <summary>
        /// 更新任务状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="taskState"></param>
        public int UpdateState(long id, TaskState taskState)
        {
            var sql = "UPDATE `Task` SET `State`=@taskState WHERE `Id`=@id;";
            return db.ExecuteNonQuery(sql, new { id, taskState });
        }
        /// <summary>
        /// 更新多个任务的状态
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="taskState"></param>
        public int UpdateState(long[] ids, TaskState taskState)
        {
            var sql = $"UPDATE `Task` SET `State`=@taskState WHERE `Id` IN ({ids2str(ids)});";
            return db.ExecuteNonQuery(sql, new { taskState });
        }
        /// <summary>
        /// 设置任务的开始时间为当前时间
        /// </summary>
        /// <param name="id"></param>
        public void SetStartTime(long id)
        {
            var sql = $"UPDATE `Task` SET `StartTime`=NOW() WHERE `Id`={id};";
            db.ExecuteNonQuery(sql);
        }
        /// <summary>
        /// 设置任务的停止时间为当前时间，同时设置任务的状态
        /// </summary>
        /// <param name="id"></param>
        public void SetStopTime(long id, TaskState taskState)
        {
            var sql = $"UPDATE `Task` SET `StopTime`=NOW(),`State`=@taskState WHERE `Id`={id};";
            db.ExecuteNonQuery(sql, new { taskState });
        }
        /// <summary>
        /// 修改任务的过期状态
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="isExpired"></param>
        /// <returns></returns>
        public int UpdateIsExpired(long[] ids, bool isExpired)
        {
            var sql = $"UPDATE `Task` SET `IsExpired`=@isExpired WHERE `Id` IN ({ids2str(ids)});";
            return db.ExecuteNonQuery(sql, new { isExpired });
        }
        /// <summary>
        /// Id数组转换为逗号分隔的字符串
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private string ids2str(long[] ids)
        {
            if (ids == null || ids.Length == 0)
            {
                throw new Exception("必须要指定任务Id。");
            }
            if (ids.Length > 200)
            {
                throw new Exception("不要一次修改过多的任务。");
            }
            List<string> list = new List<string>();
            foreach (long id in ids)
            {
                list.Add(id.ToString());
            }
            return string.Join(",", list.ToArray());
        }
        /// <summary>
        /// 删除标记为过期的任务
        /// </summary>
        /// <returns></returns>
        public int DeleteExpiredTasks()
        {
            var sql = "DELETE FROM `Task` WHERE `IsExpired`=1;";
            return db.ExecuteNonQuery(sql);
        }
        /// <summary>
        /// 删除已经过期且状态为“正在执行”的任务
        /// </summary>
        /// <param name="expiredspan"></param>
        /// <returns></returns>
        public int DeleteExpiredTasks(TimeSpan expiredspan)
        {
            var etime = DateTime.Now - expiredspan;
            var sql = "DELETE FROM `Task` WHERE `State`=1 AND `CreateTime`<=@etime;";
            return db.ExecuteNonQuery(sql, new { etime });
        }
    }
}
